package org.vectrics.recruiter.struts.admin;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.jsp.JspException;

import org.apache.log4j.Category;
import org.apache.struts.action.ActionMessage;
import org.vectrics.SystemException;
import org.vectrics.common.db.ExpirableUtils;
import org.vectrics.common.db.SimpleCodedObject;
import org.vectrics.domain.Domain;
import org.vectrics.hibernate.ThreadProperties;
import org.vectrics.history.HistoryProvider;
import org.vectrics.provider.CoreServiceLocator;
import org.vectrics.recruiter.RecruitServiceLocator;
import org.vectrics.recruiter.job.Job;
import org.vectrics.recruiter.job.JobCandidate;
import org.vectrics.recruiter.job.JobCandidateStatusReasonType;
import org.vectrics.recruiter.job.JobCandidateStatusType;
import org.vectrics.recruiter.user.CandidateInfo;
import org.vectrics.recruiter.user.Interview;
import org.vectrics.recruiter.user.InterviewResultType;
import org.vectrics.struts.Request;
import org.vectrics.struts.VectricsActionData;
import org.vectrics.struts.VectricsStrutsAction;
import org.vectrics.user.Person;
import org.vectrics.user.PersonEncounterStatusType;

public class SaveInterviewAction extends VectricsStrutsAction {
    private static Category log = Category.getInstance(SaveInterviewAction.class);

    public static String LOCATION_PARAM = "location";

    boolean newInterviewCreated = false;

    /**
     * Save the interview.
     */
    @Override
    public String doExecute(final VectricsActionData actionData) throws JspException {
        Request request = actionData.getRequest();
        String forward = "success";

        InterviewForm form = (InterviewForm) actionData.getForm();

        boolean cancelButtonPressed = actionData.wasButtonPressed("cancel");

        if (form == null) {
            log.error("form is null");
            throw new JspException("Action expected interview form to not be NULL");
        } else {
            log.info("Form class = " + form.getClass().getName());
        }

        String interviewId = form.getId();
        JobCandidate jobCandidate = null;
        Interview interview = null;
        ThreadProperties.getSession().clear();
        
        if (interviewId == null || interviewId.trim().length() <= 0) {
            log.info("ID of existing interview not passes - create new interview");
            Long jobId = new Long(form.getJobId());
            Job job = RecruitServiceLocator.getJobProvider().findJob(jobId);
            job.getJobCandidates();
            Person person = CoreServiceLocator.getPersonService().findPersonById(new Long(form.getPersonId()));
            CandidateInfo candidate = RecruitServiceLocator.getRecruitUserService().createCandidateInfoIfNotExist(
                    person);
            RecruitServiceLocator.getRecruitUserService().updateCandidateInfo(candidate);

            if (job.findJobCandidate(candidate) == null) {
                jobCandidate = job.addJobCandidate(candidate);
                RecruitServiceLocator.getJobProvider().updateJobCandidate(jobCandidate);
                RecruitServiceLocator.getJobProvider().updateJob(job);
                actionData.getRequest().addParameter("jobCandidateId", jobCandidate.getId().toString());
                jobCandidate.setStatus(JobCandidateStatusType.STATUS_CANDIDATE_APPLIED, job.getPrimaryRecruiter());
                RecruitServiceLocator.getJobProvider().updateJobCandidate(jobCandidate);
            }

            ThreadProperties.getSession().evict(job);
            job = RecruitServiceLocator.getJobProvider().findJob(jobId);
            jobCandidate = job.findJobCandidate(candidate);
            request.setAttribute("jobCandidateId", jobCandidate.getId().toString());
            if (!cancelButtonPressed) {
                log.debug("creating interview");
                newInterviewCreated = true;
                form.setNewInterviewCreated("true");
                interview = RecruitServiceLocator.getRecruitUserService().createInterview(jobCandidate,
                        job.getPrimaryRecruiter());
            }
        } else {
            log.debug("interview id was given, looking up interview");
            interview = RecruitServiceLocator.getRecruitUserService().findInterviewById(new Long(interviewId));
            Person person = interview.getPerson();
            CandidateInfo candidate = RecruitServiceLocator.getRecruitUserService().createCandidateInfoIfNotExist(
                    person);
            if (candidate.getId() == null) {
                RecruitServiceLocator.getRecruitUserService().updateCandidateInfo(candidate);
            }

            Job job = interview.getJob();
            if (job != null) {
                jobCandidate = job.findJobCandidate(candidate);
                request.setAttribute("jobCandidateId", jobCandidate.getId().toString());
            }

            if (log.isDebugEnabled()) {
                log.debug("Updating interview: " + interview.getId());
            }
        }
        
    	
        if (!cancelButtonPressed) {
            try {
                log.debug("setting data for interview");
                interview.setDescription(form.getDescription());
                interview.setFollowUp(form.getFollowUp());
                if (form.getInterviewerId() != null) {
                    interview.setLeadPerson(CoreServiceLocator.getPersonService().findPersonById(
                            new Long(form.getInterviewerId())));
                }
                interview.setNotes(form.getNotes());
                // interview.setResult(form.getResult());
                
                interview.setInterviewInstance(RecruitServiceLocator.getInterviewSearcher().getInterviewInstance(form.getInterviewInstance()));
                
                String startDateString = form.getStartDate();
                Date startDate = null;
                if (startDateString != null) {
                    String dateStr = startDateString + " " + form.getStartHour() + ":" + form.getStartMinute();
                    log.info("Start date/time: " + dateStr);
                    SimpleDateFormat dateFormatter = new SimpleDateFormat("d/M/y h:m");
                    startDate = dateFormatter.parse(dateStr);
                    interview.setDateStart(startDate);
                }

                log.info("Converted start date/time: " + startDate.toString());
                String minutos = form.getMinutes();
                if (!minutos.trim().equals("")) {
                    Integer minutes = new Integer(form.getMinutes());
                    long endTime = startDate.getTime() + minutes.intValue() * 60 * 1000;
                    Date endDate = new Date(endTime);
                    interview.setDateEnd(endDate);
                }

                PersonEncounterStatusType statusType = RecruitServiceLocator.getPersonService()
                        .findPersonEncounterStatusType(form.getStatusCode());
                if (statusType == null)
                    throw new SystemException("Could not find status type for code: " + form.getStatusCode());
                else {
                    if (log.isDebugEnabled()) {
                        log.debug("Interview status being set: " + statusType);
                    }
                }
                interview.setStatusType(statusType);

                if (log.isDebugEnabled()) {
                    log.debug(" - Interview dateStart: " + interview.getDateStart());
                    log.debug(" - Interview result:    " + interview.getResult());
                    log.debug(" - Interview status:    " + interview.getStatusType().getName());
                    log.debug(" - Interview desc:      " + interview.getDescription());
                }
                RecruitServiceLocator.getRecruitUserService().updateInterview(interview);

                if (interview.getResultType() != null) {
                    form.setResultCode(interview.getResultType().getCode());
                }
                boolean statusRequiresInterviewResult = doesStatusRequireInterviewResult(statusType, actionData);
                if (statusRequiresInterviewResult) {
                    form.setId(interview.getId().toString());
                    form.setResult(interview.getResult());
                    forward = "get.interview.result";
                } else {
                    log.debug("If interview has a result type, clear it.  The result would be left over from a previous save and this save (with the status code) doesn't have results.");
                    if (interview.getResultType() != null) {
                        interview.setResultType(null);
                        RecruitServiceLocator.getRecruitUserService().updateInterview(interview);
                    }
                }
                // Cambio el estado de la persona a in interview
                // Si no se puede cambiar porque el workflow no lo permite,
                // no deberia influir en nada.
                try {
                    changeState(jobCandidate, ThreadProperties.getPerson());
                } catch (Exception ex) {
                    log.error("No se puede cambiar al estado in interview ", ex);
                }

                ThreadProperties.forcedCommit();
            } catch (Exception ex) {
                log.error("Exception copying properties from interview form", ex);
                throw new JspException("Exception copying properties from interview form", ex);
            }

        } else {
            forward = "cancel";
        }

        return forward;
    }

    private boolean doesStatusRequireInterviewResult(final PersonEncounterStatusType statusType,
            final VectricsActionData actionData) {
        Request request = actionData.getRequest();
        Collection resultTypes = RecruitServiceLocator.getRecruitUserService().findInterviewResultTypesForStatus(
                statusType);
        if (resultTypes.size() > 0) {
            Collection resultTypeDescriptions = new ArrayList();
            Iterator iter = resultTypes.iterator();
            while (iter.hasNext()) {
                InterviewResultType resultType = (InterviewResultType) iter.next();
                SimpleCodedObject resultTypeWithDescription = new SimpleCodedObject();
                resultTypeWithDescription.setCode(resultType.getCode());
                resultTypeWithDescription.setName(actionData.getPhrase(resultType.getDescriptionCode()));
                resultTypeDescriptions.add(resultTypeWithDescription);
            }
            request.setAttribute("resultTypes", resultTypeDescriptions);
            actionData.setRequestForm(actionData.getForm());

        }

        return resultTypes.size() > 0;
    }

    protected void sendEvent(final HttpServletRequest request, final Interview interview, final Person authPerson) {
        String interviewerName = "Not Given";
        if (interview.getLeadPerson() != null) {
            interviewerName = interview.getLeadPerson().getName();
        }

        if (newInterviewCreated) {
            HistoryProvider.getInstance().createHistory(
                    Interview.OBJECT_TYPE,
                    interview.getId().toString(),
                    "intrv_create",
                    authPerson,
                    "Created a new interview with the web interface.  Candidate: " + interview.getPerson().getName()
                            + "  Interviewer: " + interviewerName);
        } else {
            HistoryProvider.getInstance().createHistory(
                    Job.OBJECT_TYPE,
                    interview.getId().toString(),
                    "intrv_update",
                    authPerson,
                    "Interview information changed with the web interface.  Candidate: "
                            + interview.getPerson().getName() + "  Interviewer: " + interviewerName);
        }
    }

    /**
     * Metodo que pasa al candidato al estado "In Interview" .
     * 
     * @param candidato
     * @param authPerson
     */
    private void changeState(final JobCandidate jobCandidate, final Person authPerson) {
        // Mensaje que va a aparecer en la nota
        String Phrase = "";
        // Obtengo el dominio
        Domain domain = ThreadProperties.getDomain();
        // Busco los estados.
        JobCandidateStatusType oldStatusType = jobCandidate.getCurrentStatus().getStatusType();

        if (!oldStatusType.getCode().equalsIgnoreCase("hired")) {
            JobCandidateStatusType newStatusType = RecruitServiceLocator.getJobProvider().findJobCandidateStatusType(
                    "in.interview");

            JobCandidateStatusReasonType defaultStatusReason = RecruitServiceLocator.getJobProvider()
                    .findDefaultCandidateStatusReason(domain, oldStatusType.getCode(), newStatusType.getCode());
            // Seteo los estados
            jobCandidate.setStatus(newStatusType.getCode(), defaultStatusReason, authPerson);
            jobCandidate.setStrength(new Long("0"));
            jobCandidate.setNote(Phrase);
            jobCandidate.setResume(null);
            // Guardo
            RecruitServiceLocator.getJobProvider().updateJobCandidate(jobCandidate);
            ExpirableUtils.validateNoGaps(jobCandidate.getStatusList());
            ExpirableUtils.validateNoGapsNoEnd(jobCandidate.getStatusList());

            RecruitServiceLocator.getJobProvider().updateJob(jobCandidate.getJob());
        }

    }

}
